package com.garmin.gh.apps.wellnessmonitor.service;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.garmin.gh.apps.wellnessmonitor.dao.LoadSummaryDataDao;
import com.garmin.gh.apps.wellnessmonitor.dao.h2.UserPartnerDao;
import com.garmin.gh.apps.wellnessmonitor.dao.h2.WellnessDao;
import com.garmin.gh.apps.wellnessmonitor.domain.ping.PingNotificationData;

@Service
@Component
public class UploadService {

	private static final Logger logger = LoggerFactory.getLogger(UploadService.class);

	private static final String PING = "ping";

	ExecutorService executor = Executors.newFixedThreadPool(100);

	@Autowired
	UserPartnerDao userPartnerDao;

	@Autowired
	WellnessDao wellnessDao;

	@Autowired
	LoadSummaryDataDao loadSummaryData;
	
	@Autowired
    OauthConfiguration oauthConfig;

	// Your Health API Consumer Key
	@Value("${oauth.consumerkey}")
	private String consumerkey;

	@Value("${oauth.consumerSecret}")
	private String consumerSecret;

	ObjectMapper jackson = new ObjectMapper();

	// processing each ping notification and calling healthapi to get summary
	// data.

	public ResponseEntity<String> invokeHealthApi(List<PingNotificationData> pingNotifications, String summaryDomian) {
		for (PingNotificationData notification : pingNotifications) {
			executor.execute(new Runnable() {

				@Override
				public void run() {
					try {

						logger.info(
								" {} ping notification data:userAccessToken:{}uploadStartTime:{}uploadEndTime:{}callBackUrl{}",
								summaryDomian, notification.getUserAccessToken(),
								notification.getUploadStartTimeInSeconds(), notification.getUploadEndTimeInSeconds(),
								notification.getCallbackURL());
						logger.info("calling rest api to upload {} data", summaryDomian);
						String SummaryData = retrieveSummaryDataByUploadTime(summaryDomian,
								notification.getUserAccessToken(), notification.getCallbackURL());
						logger.info("{} info for userAccessToken:{}:-{}", summaryDomian,
								notification.getUserAccessToken(), SummaryData);
						long timeStamp = System.currentTimeMillis();
			            loadSummaryData.savePingData(summaryDomian, PING, consumerkey, notification.getUserAccessToken(), timeStamp, SummaryData);

					} catch (Exception e) {
						logger.error("error in exception:" + e.getMessage());
					}
				}
			}

			);

		}

		logger.info("sending acknowledgement - 200  for {} ping notification service", summaryDomian);
		return new ResponseEntity<String>(HttpStatus.OK);
	}

	/*
	 * calling Rest APIs to get Summary data for each Summary Domain.
	 */
	public String retrieveSummaryDataByUploadTime(String summaryName, String userAccessToken, String callbackURL) {
		String summaryInfo = null;
		try {

			RestTemplate restTemplate = oauthConfig.getRestTemplate(userAccessToken, userPartnerDao.getUserAccessSecret(userAccessToken));
			ResponseEntity<String> result =  restTemplate.exchange(callbackURL, HttpMethod.GET, oauthConfig.httpEntity(), String.class);
			summaryInfo = prettyPrint(result.getBody().toString());
			
		}

		catch (Exception e) {
			logger.error("failed to get summary data:" + e.getMessage());
		}
		
		return summaryInfo;
	}

	private String prettyPrint(String data)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		return jackson.writerWithDefaultPrettyPrinter().writeValueAsString(jackson.readValue(data, Object.class));
	}

}